/*
   Copyright 2022 cmanlh

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
/**
 * select box
 * 
 */
import JscConfig from './config.js';
import JscDatabind from './databind.js';
import JscMQ from './mq.js';
import JscConstant from './constant.js';
export default class JscSelect extends JscDatabind {
    static get observedAttributes() { return ['required', 'readonly', 'disabled', 'placeholder', 'value', 'jscbind', 'multiple', 'optionwidth', 'options'] }

    #value;
    #input = undefined;
    #container = undefined;
    #clear = undefined;
    #optionWidth = undefined;
    #data = [];
    #required = false;
    #multiple = false;
    #jscBind = null;
    #cancelHandler = null;
    #currentLi = null;

    constructor() {
        super();
        this.#init();
        this.#render();
    }

    connectedCallback() {
        this.#bindEventForInput();
    }

    disconnectedCallback() {
        if (null != this.#cancelHandler) {
            document.removeEventListener('click', this.#cancelHandler);
        }
    }

    attributeChangedCallback(name, oldValue, newValue) {
        switch (name) {
            case 'value': {
                if (oldValue != newValue) {
                    this.value = newValue;
                }
                break;
            }
            case 'required': {
                if (oldValue != newValue) {
                    if (null == newValue) {
                        this.#required = false;
                    } else {
                        this.#required == newValue;
                    }
                }
                break;
            }
            case 'disabled': {
                if (oldValue != newValue) {
                    if (newValue || '' == newValue) {
                        this.#input.setAttribute('disabled', true);
                    } else {
                        this.#input.removeAttribute('disabled');
                    }
                }
                break;
            }
            case 'jscbind': {
                if (oldValue != newValue) {
                    this.#jscBind = newValue;
                }
                break;
            }
        }
    }

    bindRefresh(bindStamp) {
        if (super.bindRefresh(bindStamp)) {
            if (null != this.bind && null != this.#jscBind) {
                this.#value = this.fetchBindValue(this.#jscBind);
                this.#renderSelected();
            }
        }
    }

    set value(val) {
        let self = this;
        let oldValue = self.#value;
        if (oldValue == val) {
            return;
        }
        self.#value = val;
        self.#renderSelected();
        self.updateBindValue(this.#jscBind, this.#value);
    }

    #renderSelected() {
        let self = this;
        if (self.#multiple) {
            if (null == self.#value) {
                self.#container.querySelectorAll('li.selected').forEach((selectedLi) => {
                    selectedLi.classList.remove('selected');
                });
                self.#input.value = '';
                self.#input.title = self.#input.value;
            } else {
                let lables = '';
                let values = self.#value.split(',');
                self.#container.querySelectorAll('li').forEach((li) => {
                    let selected = false;
                    for (let i = 0; i < values.length; i++) {
                        if (li.getAttribute('optionValue') == values[i]) {
                            lables = lables.concat(',').concat(li.textContent);
                            if (!li.classList.contains('selected')) {
                                li.classList.add('selected');
                            }
                            selected = true;
                            break;
                        }
                    }
                    if (!selected) {
                        if (li.classList.contains('selected')) {
                            li.classList.remove('selected');
                        }
                    }
                });

                self.#input.value = lables.replace(',', '');
                self.#input.title = self.#input.value;
            }
        } else {
            if (null != self.#currentLi) {
                self.#currentLi.classList.remove('selected');
                self.#currentLi = null;
            }
            if (null == self.#value) {
                self.#input.value = '';
                self.#input.title = self.#input.value;
            } else {
                let lis = self.#container.querySelectorAll('li');
                for (let i = 0; i < lis.length; i++) {
                    let li = lis[i];
                    if (li.getAttribute('optionValue') == self.#value) {
                        li.classList.add('selected');
                        self.#input.value = li.textContent;
                        self.#input.title = self.#input.value;
                    };
                }
            }
        }
    }

    get value() {
        return this.#value;
    }

    set data(val) {
        this.#data = val;
        this.#renderOptions();
        this.value = null;
    }

    get data() {
        return this.#data;
    }

    #init() {
        let multiple = this.getAttribute('multiple');
        if (null == multiple) {
            this.#multiple = false;
        } else {
            this.#multiple = true;
        }

        let required = this.getAttribute('required');
        if (null == required) {
            this.#required = false;
        } else {
            this.#required = true;
        }

        this.#jscBind = this.getAttribute('jscbind');
        this.#optionWidth = this.getAttribute('optionWidth');
    }

    #render() {
        const shadowRoot = this.attachShadow({ mode: 'open' });
        shadowRoot.innerHTML = `
        <link rel='stylesheet' type='text/css' href='${JscConfig.cssUrl}'/>
        <input type='text' class='inputSelect inputSelectInit' readonly>
        <span title='清空' class='inputSelectClear'></span>
        <div class='inputSelectContainer active' style='display:none;'><ul></ul></div>
        `;
        this.#input = this.shadowRoot.querySelector('input');
        this.#container = this.shadowRoot.querySelector('div');
        this.#clear = this.shadowRoot.querySelector('span');

        if (this.getAttribute('placeholder')) {
            this.#input.setAttribute('placeholder', this.getAttribute('placeholder'));
        }

        if (this.getAttribute('disabled')) {
            this.#input.setAttribute('disabled', true);
        }

        let _options = this.getAttribute('options');
        if (_options) {
            let self = this;
            let options = JSON.parse(_options);
            options.forEach((option) => {
                self.#data.push({ value: option.value, label: option.label });
            });
        }

        this.#renderOptions();
    }

    #renderOptions() {
        this.#currentLi = null;
        let ul = this.#container.querySelector('ul');
        let lis = ul.querySelectorAll('li');
        if (lis.length >= this.#data.length) {
            const maxIdx = this.#data.length - 1;
            for (let idx = 0; idx < lis.length; idx++) {
                let li = lis[idx];
                if (idx > maxIdx) {
                    li.remove();
                } else {
                    let data = this.#data[idx];
                    li.title = data.label;
                    li.textContent = data.label;
                    li.setAttribute('optionValue', data.value);
                    li.classList.remove('selected');
                }
            }
        } else {
            for (let idx = 0; idx < lis.length; idx++) {
                let li = lis[idx];
                let data = this.#data[idx];
                li.title = data.label;
                li.textContent = data.label;
                li.setAttribute('optionValue', data.value);
                li.classList.remove('selected');
            }

            let newNodes = document.createDocumentFragment();
            for (let idx = lis.length; idx < this.#data.length; idx++) {
                let newLi = document.createElement('li');
                let data = this.#data[idx];
                newLi.title = data.label;
                newLi.textContent = data.label;
                newLi.setAttribute('optionValue', data.value);
                newNodes.appendChild(newLi);
            }
            ul.appendChild(newNodes);
        }
    }

    #bindEventForInput() {
        let self = this;
        self.#input.addEventListener('click', function (e) {
            if ('block' == self.#container.style.display) {
                self.#container.style.display = 'none';
                self.#input.classList.remove('inputSelectActive');
                self.#input.classList.add('inputSelectInit');
                return
            }
            self.#input.classList.add('inputSelectActive');
            self.#input.classList.remove('inputSelectInit');

            self.#container.style.display = 'block';
            let inputStyle = window.getComputedStyle(self.#input);
            if (null == self.#optionWidth) {
                self.#container.style.width = parseFloat(inputStyle.width) + parseFloat(inputStyle.borderLeftWidth) + parseFloat(inputStyle.borderRightWidth) + 'px';
            } else if (self.#optionWidth > 0) {
                self.#container.style.width = self.#optionWidth + 'px';
            }
            self.#container.style.top = self.#input.offsetTop + parseFloat(inputStyle.height) + parseFloat(inputStyle.borderTopWidth) + parseFloat(inputStyle.borderBottomWidth) + 1 + 'px';
            self.#container.style.left = self.#input.offsetLeft + 'px';
        });

        let clearDisplayTimer = null;
        self.#input.addEventListener('mouseover', function (e) {
            if (null != self.#value) {
                let inputStyle = window.getComputedStyle(self.#input);
                self.#clear.style.display = 'inline-block';
                self.#clear.style.top = self.#input.offsetTop + 7 + 'px';
                self.#clear.style.left = self.#input.offsetLeft + parseFloat(inputStyle.width) + parseFloat(inputStyle.borderLeftWidth) + parseFloat(inputStyle.borderRightWidth) - 26 + 'px';
                if (null != clearDisplayTimer) {
                    clearTimeout(clearDisplayTimer);
                }
            }
        });

        self.#input.addEventListener('mouseleave', function (e) {
            clearDisplayTimer = setTimeout(function () {
                self.#clear.style.display = 'none';
            }, 50);
        });

        self.#clear.addEventListener('click', function (e) {
            self.value = null;
            self.#clear.style.display = 'none';
            self.#container.style.display = 'none';
            self.#input.classList.remove('inputSelectActive');
            self.#input.classList.add('inputSelectInit');
        });

        self.#container.addEventListener('click', function (e) {
            if (e.composed) {
                let li = e.composedPath()[0];
                if (self.#multiple) {
                    li.classList.toggle('selected');
                    let values = '';
                    let lables = '';
                    self.#container.querySelectorAll('li.selected').forEach((selectedLi) => {
                        values = values.concat(',').concat(selectedLi.getAttribute('optionValue'));
                        lables = lables.concat(',').concat(selectedLi.textContent);
                    });

                    self.value = values.replace(',', '');
                    self.#input.value = lables.replace(',', '');
                    self.#input.title = self.#input.value;
                } else {
                    if (li != self.#currentLi) {
                        self.value = li.getAttribute('optionValue');
                        self.#input.value = li.textContent;
                        self.#input.title = self.#input.value;
                        if (null != self.#currentLi) {
                            self.#currentLi.classList.remove('selected');
                        }
                        self.#currentLi = li;
                        li.classList.add('selected');
                    }
                }
            }
        });

        self.#cancelHandler = function (e) {
            if (e.target != self && 'block' == self.#container.style.display) {
                self.#container.style.display = 'none';
                self.#input.classList.remove('inputSelectActive');
                self.#input.classList.add('inputSelectInit');
                return
            }
        };
        
        JscMQ.register(JscConstant.EventId.POPUP_CONTENT_HIDE,self.#cancelHandler);
    }

    checkValidity() {
        let errMsg = '';
        if (this.#required && (undefined == this.#value || null == this.#value || '' == this.#value)) {
            errMsg = '该字段不能为空';
        }

        this.#input.setCustomValidity(errMsg);
        this.#input.reportValidity();

        if ('' === errMsg) {
            return true;
        } else {
            return false;
        }
    }
}

if (!customElements.get('jsc-select')) {
    window.customElements.define("jsc-select", JscSelect);
}

if (undefined == window.JSC_FLAG_SET) {
    window.JSC_FLAG_SET = {};
}

if (null == window.JSC_FLAG_SET.registPopupContentHideEvent) {
    window.JSC_FLAG_SET.registPopupContentHideEvent = true;

    document.addEventListener('click', function (e) {
        JscMQ.postMsg(JscConstant.EventId.POPUP_CONTENT_HIDE,e);
    });
}